﻿#include "experimentui.h"
#include "ui_experimentui.h"
#include "ui_experimentpropertyui.h"
#include "ui_experimentrunui.h"


ExperimentUi::ExperimentUi(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ExperimentUi)
{
    ui->setupUi(this);

    /* 实例化页面 */
    experimentPropertyUi = new ExperimentPropertyUi();
    experimentMethodUi = new ExperimentMethodUi();
    experimentPlateUi = new ExperimentPlateUi();
    experimentRunUi = new ExperimentRunUi();
    experimentResultUi = new ExperimentResultUi();
    experimentExportUi = new ExperimentExportUi();
    /* 创建布局 */
    expPropetyLayout = new QVBoxLayout();
    expMethodLayout = new QVBoxLayout();
    expPlateLayout = new QVBoxLayout();
    expRunLayout = new QVBoxLayout();
    expResultLayout = new QVBoxLayout();
    expExportLayout = new QVBoxLayout();
    /* 添加页面 */
    expPropetyLayout->addWidget(experimentPropertyUi);
    expMethodLayout->addWidget(experimentMethodUi);
    expPlateLayout->addWidget(experimentPlateUi);
    expRunLayout->addWidget(experimentRunUi);
    expResultLayout->addWidget(experimentResultUi);
    expExportLayout->addWidget(experimentExportUi);
    /* 设置边距 */
    expPropetyLayout->setMargin(0);
    expPropetyLayout->setSpacing(0);
    expMethodLayout->setMargin(0);
    expMethodLayout->setSpacing(0);
    expPlateLayout->setMargin(0);
    expPlateLayout->setSpacing(0);
    expRunLayout->setMargin(0);
    expRunLayout->setSpacing(0);
    expResultLayout->setMargin(0);
    expResultLayout->setSpacing(0);
    expExportLayout->setMargin(0);
    expExportLayout->setSpacing(0);
    /* 添加布局 */
    ui->expProperies->setLayout(expPropetyLayout);
    ui->expMethods->setLayout(expMethodLayout);
    ui->expPlate->setLayout(expPlateLayout);
    ui->expRun->setLayout(expRunLayout);
    ui->expResults->setLayout(expResultLayout);
    ui->expExport->setLayout(expExportLayout);

    /* 实例化对象 */
    exportFileService = new ExportFileService();
    experimentService = new ExperimentService();
    procedureService = new ProcedureService();

    /* 初始化 */
    cycling = 0;
    experiment.type = "";
    experiment.coding = "";
    experiment.remarks = "";
    experiment.plate_remarks = "";
    experiment.experiment_remarks = "";
    experiment.device_id = "";
    experiment.user_name = "";
    experiment.experiment_name = "";
    experiment.reaction_volume = "";
    previousTabbarIndex = 0;
    isImport = false;

    cusMsg = new CustomMessageBox();

    /* 获取实验id */
    this->id = this->experimentService->createExperiment(this->experiment);
    this->experiment.experiment_id = this->id;

    /* 反写实验id */
    experimentPropertyUi->writeBackExperimentId(this->id);

    /* 初始化wlk文件名 */
    wlkFileName = "";

    //    LOG << "this->experiment.experiment_id" << this->experiment.experiment_id;

    /* 设备改变 */
    connect(experimentPropertyUi->ui->sComputer, SIGNAL(currentIndexChanged(int)), this, SLOT(currentActiveChanged(int)));
    connect(experimentRunUi->ui->runningDevice, SIGNAL(currentIndexChanged(int)), this, SLOT(currentActiveChanged(int)));

    /* 下一步按钮 */
    /* 实验属性 - 扩增 */
    connect(experimentPropertyUi, &ExperimentPropertyUi::nextEvent, this, [=](){
        /* 跳转到下一页 */
        ui->stepBar->setCurrentIndex(1);
    });
    /* 扩增 - 反应板 */
    connect(experimentMethodUi, &ExperimentMethodUi::nextEvent, this, [=](){
        /* 跳转到下一页 */
        ui->stepBar->setCurrentIndex(2);
    });
    /* 反应板 - 运行 */
    connect(experimentPlateUi, &ExperimentPlateUi::nextEvent, this, [=](){
        /* 跳转到下一页 */
        ui->stepBar->setCurrentIndex(3);
    });
    /* 运行 - 结果 */
    connect(experimentRunUi, &ExperimentRunUi::nextEvent, this, [=](){
        /* 跳转到下一页 */
        ui->stepBar->setCurrentIndex(4);
    });
    /* 结果 - 导出 */
    connect(experimentResultUi, &ExperimentResultUi::nextEvent, this, [=](){
        /* 跳转到下一页 */
        ui->stepBar->setCurrentIndex(5);
    });

    /* 上一步按钮 */
    /* 扩增 - 实验属性  */
    connect(experimentMethodUi, &ExperimentMethodUi::previousEvent, this, [=](){
        ui->stepBar->setCurrentIndex(0);
    });
    /* 反应板 - 扩增 */
    connect(experimentPlateUi, &ExperimentPlateUi::previousEvent, this, [=](){
        ui->stepBar->setCurrentIndex(1);
    });
    /* 运行 - 反应板 */
    connect(experimentRunUi, &ExperimentRunUi::previousEvent, this, [=](){
        ui->stepBar->setCurrentIndex(2);
    });
    /* 结果 - 运行 */
    connect(experimentResultUi, &ExperimentResultUi::previousEvent, this, [=](){
        ui->stepBar->setCurrentIndex(3);
    });
    /* 导出 - 结果 */
    connect(experimentExportUi, &ExperimentExportUi::previousEvent, this, [=](){
        ui->stepBar->setCurrentIndex(4);
    });

    /* 保存按钮 */
    /* 实验属性 */
    connect(experimentPropertyUi, &ExperimentPropertyUi::saveEvent, this, &ExperimentUi::saveWlkData);
    /* 扩增程序 */
    connect(experimentMethodUi, &ExperimentMethodUi::saveEvent, this, &ExperimentUi::saveWlkData);
    /* 反应板 */
    connect(experimentPlateUi, &ExperimentPlateUi::saveEvent, this, &ExperimentUi::saveWlkData);
    /* 结果 */
    connect(experimentResultUi, &ExperimentResultUi::saveEvent, this, &ExperimentUi::saveWlkData);
    /* 报告 */
    connect(experimentExportUi, &ExperimentExportUi::saveEvent, this, &ExperimentUi::saveWlkData);

    /* 实验信息改变 */
    connect(experimentPropertyUi, &ExperimentPropertyUi::experimentInfoChanged, this, [=](Experiment experiment){
        /* 修改主页实验名称 */
        emit ExperimentUi::changeHomePageTabName(experiment.experiment_name);
    });

    /* tab 页变化 */
    connect(ui->stepBar, &QTabWidget::currentChanged, this, [=](int index){
        /* 发送信号，处理页面变化，更新页面数据 */
        this->updatePageInfos(index, false);
    });

    /* 挂载页面数据 */
    connect(this, &ExperimentUi::mountPage, this, &ExperimentUi::mountPageInfos, Qt::QueuedConnection);


    /* 运行：实验结束，渲染结果曲线 */
    connect(experimentRunUi, &ExperimentRunUi::successRenderResultCurve, this, [=](){
        /* 所有组件生效 */;
        experimentPlateUi->allComponentsValid();
        experimentPropertyUi->allComponentsValid();
        experimentMethodUi->allComponentsValid();
        experimentExportUi->allComponentsValid();

        /* 写入荧光数据 */
        this->saveYingguangDataList = experimentRunUi->saveYingguangDataList;
        experimentResultUi->saveYingguangDataList = experimentRunUi->saveYingguangDataList;
        experimentResultUi->saveYingguangDataListDuplicate = experimentRunUi->saveYingguangDataList;
        /* 更新结果页面自动导出标识位 */
        experimentResultUi->autoExportFlag = true;
        /* 渲染曲线 */
        experimentResultUi->renderResultCurve();

        /* 如果荧光曲线有值，那么除反应板之外的所有页面均不可修改 */
        if(experimentRunUi->saveYingguangDataList.size() != 0){
            experimentPropertyUi->allComponentsInvalid();
            experimentMethodUi->allComponentsInvalid();
        }

        /* 更新所有设备信息 */
        emit ExperimentUi::updateActiveDeviceList();

        /* 自动保存 */
        this->runningSave();
    }, Qt::QueuedConnection);

    /* 运行：更新活跃设备列表 */
    connect(experimentRunUi, &ExperimentRunUi::updateInactiveDeviceList, this, [=](){
        /* 设置设备下拉框可用状态 */
        ConnectedDeviceStruct cDev = currentSelectedDevice.value<ConnectedDeviceStruct>();
        for(int i = 0; i < connectDeviceInfo.size(); i++){
            if(cDev.dev.id == connectDeviceInfo[i].dev.id){
                if(connectDeviceInfo[i].dev.status == "运行中"){
                    /* 下拉框不可用 */
                    experimentPropertyUi->ui->sComputer->setEnabled(false);
                    experimentRunUi->ui->runningDevice->setEnabled(false);
                }
                else {
                    /* 下拉框可用 */
                    experimentPropertyUi->ui->sComputer->setEnabled(true);
                    experimentRunUi->ui->runningDevice->setEnabled(true);
                }
                break;
            }
        }
        LOG << "所有组件失效";
    });

    /* 运行：清空结果曲线 */
    connect(experimentRunUi, &ExperimentRunUi::clearResultCurve, this, [=](){
        /* 所有组件失效 */
        experimentPropertyUi->allComponentsInvalid();
        experimentMethodUi->allComponentsInvalid();
        experimentPlateUi->allComponentsInvalid();
        experimentExportUi->allComponentsInvalid();
        //        experimentResultUi->clearResultCurve();
        /* 更新所有设备信息 */
        emit ExperimentUi::updateActiveDeviceList();
        /* 获取并保存实验设备id */
        this->experiment.device_id = experimentRunUi->cDevS.dev.id;
    });

    /* 运行：保存实验信息 */
    connect(experimentRunUi, &ExperimentRunUi::startSaveExperimentInfo, this, &ExperimentUi::forceSaveWlkData);

    /* 运行：渲染实验恢复实验列表 */
    connect(experimentRunUi, &ExperimentRunUi::renderRestoreList, this, [=](){
        emit ExperimentUi::renderRestoreList();
    });

    /* 运行：渲染运行状态颜色到Tab页上 */
    connect(experimentRunUi, &ExperimentRunUi::sigShowRunningStatus, this, [=](QString status){
        emit ExperimentUi::sigShowRunningStatus(status);
    });

    /* 结果：自动导出 */
    connect(experimentResultUi, &ExperimentResultUi::sigExport, this, &ExperimentUi::slotExport);

    /* 关闭页面 */
    connect(experimentPlateUi, &ExperimentPlateUi::closePage, this, &ExperimentUi::slotChildClosePage);

//    /* 导出：实验（手动）导出 */
//    connect(experimentExportUi, &ExperimentExportUi::sigExport, this, &ExperimentUi::slotExport);
}

ExperimentUi::~ExperimentUi()
{
    delete ui;
}

/* 页面跳转，更新所有页面数据 */
void ExperimentUi::updatePageInfos(int index, bool init){
    Experiment tExp;
    std::tuple<int, int, int, int, int> tBasicProcedureInfo;
    std::tuple<QString, ReactionPlate, QString> reactionPlateInfo;
    int liquidVolume, stepCount, stageCount, totalrunningTime, cyclingNumber;
    ReactionPlate tReaPlate;
    QString canBi;
    QString reactionPlateRemarks;
    QHash<QString, QString> tTarLgnd;
    /* 运行时间改变标志位 */
    bool changeRunningTime = false;

    /* 所有页面组件失效 */
    ui->stepBar->setEnabled(false);

    LOG << "显示提示";

    /* 如果为 “实验属性” 页，增加判断显示，初始化时不显示 */
    if(this->previousTabbarIndex == 0 && !init){
        /* 检测实验名称是否为空 */
        if(experimentPropertyUi->ui->expName->displayText() == ""){
            cusMsg->show(this, CMsg::CWarning, "实验", "实验名称为空！");
            ui->stepBar->setCurrentIndex(0);
            return;
        }
        /* 如果为导入的设备，且设备不存在，那么给予提示 */
        if(!experimentPropertyUi->ui->sComputer->currentText().contains(" - 已连接")
                && !experimentPropertyUi->ui->sComputer->currentText().contains(" - 故障")
                && !experimentPropertyUi->ui->sComputer->currentText().contains(" - 运行中")){
            ui->stepBar->blockSignals(true); // 阻止信号
            ui->stepBar->setCurrentIndex(0); // 页面回跳
            ui->stepBar->blockSignals(false); // 解除阻止信号

            cusMsg->show(this, CCritical, "设备错误", "实验设备无效，请确认！");

            ui->stepBar->blockSignals(true); // 阻止信号
            ui->stepBar->setCurrentIndex(index); // 页面正跳
            ui->stepBar->blockSignals(false); // 解除阻止信号
        }
    }
    /* 如果为 “扩增” 页，增加判断显示，初始化时不显示 */
    else if(this->previousTabbarIndex == 1 && !init){
        /* 判断所有步骤都是否开启荧光收集 */
        if(!experimentMethodUi->allMarkedStatus()){
            ui->stepBar->blockSignals(true); // 阻止信号
            ui->stepBar->setCurrentIndex(1); // 页面回跳
            ui->stepBar->blockSignals(false); // 解除阻止信号

            cusMsg->show(this, CMsg::CCritical, "扩增程序", "未开启荧光检测，请您确认。");

            ui->stepBar->blockSignals(true); // 阻止信号
            ui->stepBar->setCurrentIndex(index); // 页面正跳
            ui->stepBar->blockSignals(false); // 解除阻止信号
        }
    }
    /* 如果为 “反应板” 页，且反应板的靶基因内容为空，增加判断显示，初始化时不显示 */
    else if(this->previousTabbarIndex == 2 && !experimentPlateUi->hasPlateTargetContent() && !init){
        ui->stepBar->blockSignals(true); // 阻止信号
        ui->stepBar->setCurrentIndex(2); // 页面回跳
        ui->stepBar->blockSignals(false); // 解除阻止信号

        cusMsg->show(this, CMsg::CCritical, "反应板", "反应板未选中任何通道，无法开始实验！");

        ui->stepBar->blockSignals(true); // 阻止信号
        ui->stepBar->setCurrentIndex(index); // 页面正跳
        ui->stepBar->blockSignals(false); // 解除阻止信号
    }

    /* 更新下标 */
    this->previousTabbarIndex = index;

    LOG << "实验属性渲染";

    /* 获取实验属性页数据 */
    tExp = experimentPropertyUi->returnPageInfos();
    /* 如果数据有变动，执行操作 */
    if(this->contrastPropertyData(tExp)){
        LOG << "实验属性数据不同";
        /* 更新数据 */
        this->propertyToMethod(tExp);
    }

    LOG << "实验属性结束";
    LOG << "开始扩增渲染";

    /* 获取扩增页面数据 */
    tBasicProcedureInfo = experimentMethodUi->returnPageInfos();
    std::tie(liquidVolume, stepCount, stageCount, totalrunningTime, cyclingNumber) = tBasicProcedureInfo;
    /* 如果数据有变动，执行操作 */

    LOG << "this->experiment.experiment_id" << this->experiment.experiment_id;

    if(this->contrastMethodData(tBasicProcedureInfo, procedureService->getProcedureData(this->experiment.experiment_id))){
        /* 如果运行时间不同，则改变运行时间标识位 */
        if(totalrunningTime != this->totalrunningTime){
            changeRunningTime = true;
        }

        /* 更新数据 */
        this->methodToPlate(liquidVolume, stepCount, stageCount, totalrunningTime);
    }

    LOG << "扩增结束";
    LOG << "开始比较反应板信息";

    /* 获取反应板页面数据 */
    reactionPlateInfo = experimentPlateUi->returnPageInfos();

    std::tie(reactionPlateRemarks, tReaPlate, canBi) = reactionPlateInfo;

    LOG << "11111111111111111111111111111>>>>>>>>>>>>>>>>>>>>>>";

    /* 如果数据有变动，执行操作 */
    this->canBi = canBi; // 先写入参比荧光
    // 进行比较
    if(this->contrastReactionData(tReaPlate) || this->cycling != cyclingNumber || changeRunningTime){

        LOG << "反应版数据不同";

        /* 更新循环数 */
        this->cycling = cyclingNumber;
        /* 写入反应版数据 */
        this->reactionPlate = tReaPlate;

        LOG << "开始更新运行页面数据>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";

        this->plateToRun();

        LOG << "开始获取targetLegend";

        /* 获取运行页面数据 */
        tTarLgnd = experimentRunUi->returnPageInfos();

        /* 写入荧光数据 */
        this->saveYingguangDataList = experimentRunUi->saveYingguangDataList;
        /* 写入靶基因数据 */
        this->targetLegend = tTarLgnd;

        LOG << "开始更新结果页面数据";

        /* 更新结果页面数据 */
        this->runToResult();

        LOG << "更新结果页面数据完毕";

        LOG << "执行了333";
    }

    LOG << "反应板结束";

    /* 获取结果页面数据 */
    this->ct = experimentResultUi->returnPageInfos();
    LOG << "获取结果页面数据结束";

    /* 更新数据 */
    this->resultToExport();


    LOG << "导出结束";

    /* 所有页面组件生效 */
    ui->stepBar->setEnabled(true);

    /* 页面光标聚焦文字框 2023.6.3*/
    experimentExportUi->setFocusToFileNameLineEdit(); // 导出页
    experimentPropertyUi->setFocusToExpNameLineEdit(); // 实验属性页
}

/* 发送实验名 */
QString ExperimentUi::sendExperimentName(){
    return experimentPropertyUi->sendExperimentName();
}

/* 渲染运行设备 */
void ExperimentUi::renderActiveDevice(){
    /* 信号阻塞 */
    experimentPropertyUi->ui->sComputer->blockSignals(true);
    experimentRunUi->ui->runningDevice->blockSignals(true);

    LOG << "信号阻塞开始";

    /* 清空设备列表 */
    experimentPropertyUi->ui->sComputer->clear();
    experimentRunUi->ui->runningDevice->clear();

    /* 初始化变量 */
    bool exist = false;


    /* 遍历设备列表，加入已连接设备 */
    for(int i = 0; i < connectDeviceInfo.size(); i++){
        LOG << "当前页面所选设备的状态" << "实验：" << thisExpIndex << "设备" << connectDeviceInfo[i].dev.name << "状态" << connectDeviceInfo[i].dev.status;
        if(connectDeviceInfo[i].dev.status != "运行中" && connectDeviceInfo[i].dev.status != "未连接"){

            LOG << "!!!!!!!!!!!!!!!!!!!!!显示！！！！！！！！" << "实验" << thisExpIndex;

            ConnectedDeviceStruct cDevStruct = connectDeviceInfo[i];
            QVariant deviceVariant = QVariant::fromValue(cDevStruct);
            /* 添加到 实验属性 设备列表中 */
            QString showDeviceInfo = connectDeviceInfo[i].dev.name + " - " + connectDeviceInfo[i].dev.status;
            /* 加入设备到 实验属性 列表中 */
            experimentPropertyUi->ui->sComputer->addItem(showDeviceInfo, deviceVariant);
            /* 添加到 运行 设备列表中 */
            QString runDeviceInfo = connectDeviceInfo[i].dev.name;
            experimentRunUi->ui->runningDevice->addItem(runDeviceInfo, deviceVariant);
        }
    }

    LOG << "当前设备表里的设备数" << experimentPropertyUi->ui->sComputer->count();

    /* 获取当前选中的设备 */
    currentSelectedDevice = experimentPropertyUi->ui->sComputer->currentData();
    // 解析当前设备
    ConnectedDeviceStruct currentDev = currentSelectedDevice.value<ConnectedDeviceStruct>();
    // 获取当前运行页面预选设备
    ConnectedDeviceStruct currentReadyDev = experimentRunUi->cDevS;

    LOG << "当前页面所选设备的状态" << "实验：" << thisExpIndex << "所选设备" << currentReadyDev.dev.name <<  "设备状态" << currentReadyDev.dev.status;

    /* 改变所选设备状态 */
    if(connectDeviceInfo.size() != 0){
        /* 如果当前实验有所选设备 */
        if(currentReadyDev.dev.name != ""){
            for(int i = 0; i < connectDeviceInfo.size(); i++){
                if(currentReadyDev.dev.id == connectDeviceInfo[i].dev.id){
                    // 如果设备正在运行
                    if(connectDeviceInfo[i].dev.status == "运行中"){
                        // 获取当前实验所选的设备
                        QVariant deviceVariant = QVariant::fromValue(connectDeviceInfo[i]);
                        // 将设备回填到设备列表中
                        experimentPropertyUi->ui->sComputer->insertItem(0, connectDeviceInfo[i].dev.name + " - " + connectDeviceInfo[i].dev.status, deviceVariant);
                        experimentRunUi->ui->runningDevice->insertItem(0, connectDeviceInfo[i].dev.name, deviceVariant);
                        // 设置选中当前设备
                        experimentPropertyUi->ui->sComputer->setCurrentIndex(0);
                        experimentRunUi->ui->runningDevice->setCurrentIndex(0);
                        connectDeviceInfo[i].isSelected = true;
                    }
                    // 如果实验没在运行
                    else {
                        for(int j = 0; j < experimentPropertyUi->ui->sComputer->count(); j++){
                            ConnectedDeviceStruct tDev = experimentPropertyUi->ui->sComputer->itemData(j).value<ConnectedDeviceStruct>();
                            /* 如果所选设备存在 */
                            if(tDev.dev.id == experimentRunUi->cDevS.dev.id){
                                experimentPropertyUi->ui->sComputer->setCurrentIndex(j);
                                experimentRunUi->ui->runningDevice->setCurrentIndex(j);
                                exist = true;
                                break;
                            }
                        }
                        if(!exist){
                            /* 如果所选设备不存在，将当前设备作为实验预选设备 */
                            experimentRunUi->cDevS = currentDev;
                            /* 同步当前设备状态 */
                            LOG << "设备不存在" << experimentRunUi->cDevS.dev.status;
                        }
                        /* 同步当前设备状态 */
                        experimentRunUi->ui->expRunStateLabel->setText(experimentRunUi->cDevS.dev.status);
                        /* 同步颜色样式 */
                        if(experimentRunUi->cDevS.dev.status == "运行中")
                            experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #086700;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
                        else if(experimentRunUi->cDevS.dev.status == "故障")
                            experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #B60000;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
                        else if(experimentRunUi->cDevS.dev.status == "已连接")
                            experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #1000EB;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
                    }
                    break;
                }
            }
        }
        /* 如果当前设备没有所选设备 */
        else {
            /* 将当前设备作为实验预选设备 */
            experimentRunUi->cDevS = currentDev;
            /* 同步当前设备状态 */
            experimentRunUi->ui->expRunStateLabel->setText(experimentRunUi->cDevS.dev.status);
            /* 同步颜色样式 */
            if(experimentRunUi->cDevS.dev.status == "运行中"){
                experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #086700;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
            }
            else if(experimentRunUi->cDevS.dev.status == "故障"){
                experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #B60000;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
            }
            else if(experimentRunUi->cDevS.dev.status == "已连接"){
                experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #1000EB;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
            }
        }
    }

    LOG << "现在当前设备表里的设备数" << experimentPropertyUi->ui->sComputer->count();

    /* 渲染设备状态 */
    experimentRunUi->ui->expRunStateLabel->setText(experimentRunUi->cDevS.dev.status);
    if(experimentRunUi->cDevS.dev.status == "已连接"){
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel{color: #1000EB;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    }
    else if(experimentRunUi->cDevS.dev.status == "故障"){
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel{color: #B60000;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    }
    else if(experimentRunUi->cDevS.dev.status == "运行中"){
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color:#086700;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    }
    else{
        experimentRunUi->ui->expRunStateLabel->setText("未知");
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel{color: #000};font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    }

    /* 如果设备列表没有文字，则其Lineedit显示空白时文字 */
    QLineEdit *propertyEdit = experimentPropertyUi->ui->sComputer->lineEdit();
    if(propertyEdit->displayText() == ""){
        experimentPropertyUi->ui->sComputer->addItem("未添加设备");
        experimentPropertyUi->ui->sComputer->setCurrentIndex(0);
    }

    /* 解除信号阻塞 */
    experimentPropertyUi->ui->sComputer->blockSignals(false);
    experimentRunUi->ui->runningDevice->blockSignals(false);
}

/* 设备改变 */
void ExperimentUi::currentActiveChanged(int index){
    /* 信号阻塞 */
    experimentPropertyUi->ui->sComputer->blockSignals(true);
    experimentRunUi->ui->runningDevice->blockSignals(true);
    /* 写入数据 */
    experimentPropertyUi->ui->sComputer->setCurrentIndex(index);
    experimentRunUi->ui->runningDevice->setCurrentIndex(index);
    currentSelectedDevice = experimentPropertyUi->ui->sComputer->currentData();

    /* 改变当前实验所选设备 */
    ConnectedDeviceStruct nextCdevS = currentSelectedDevice.value<ConnectedDeviceStruct>();
    for(int i = 0; i < connectDeviceInfo.size(); i++){
        if(nextCdevS.dev.id == connectDeviceInfo[i].dev.id){
            /* 设置为运行页预选设备 */
            experimentRunUi->cDevS = connectDeviceInfo[i];
            break;
        }
    }
    experimentRunUi->ui->expRunStateLabel->setText(experimentRunUi->cDevS.dev.status);
    /* 同步颜色样式 */
    if(experimentRunUi->cDevS.dev.status == "运行中")
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #086700;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    else if(experimentRunUi->cDevS.dev.status == "故障")
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #B60000;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    else if(experimentRunUi->cDevS.dev.status == "已连接")
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel {color: #1000EB;font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    /* 运行页面显示当前选择的设备名称和设备序列号 */
    experimentRunUi->ui->labelInfo14->setText(experimentRunUi->cDevS.dev.name);
    experimentRunUi->ui->labelInfo16->setText(experimentRunUi->cDevS.dev.serial_number);

    /* 解除信号阻塞 */
    experimentPropertyUi->ui->sComputer->blockSignals(false);
    experimentRunUi->ui->runningDevice->blockSignals(false);
}

/* 设置对象 */
void ExperimentUi::setObjs(AnalysisConfig *alysCfg, PreferencesService *preference){
    this->alysCfg = alysCfg;
    this->preferencesService = preference;
}

/* 分析配置工具栏更新 */
void ExperimentUi::updateAnalysisConfig(QList<AnalysisTarget> alysTar){
    experimentResultUi->updateDataAnalysisInfo(alysTar); // 更新结果页面数据分析数据
}

/* 返回数据分析靶基因 */
QList<AnalysisTarget> ExperimentUi::getAnalysisTarget(){
    this->alysTar = experimentResultUi->getAnalysisTarget();
    return this->alysTar;
}

/* 获取wlk文件数据 */
void ExperimentUi::getWlkData(WLKData wlkData, WLKService *wlk, QString completeFilePath){
    this->wlkData = wlkData;
    this->completeFilePath = completeFilePath;
    this->wlk = wlk;
    /* 渲染 wlk 数据 */
    this->renderWlkData();
}

/* 数据分析：获取WLKData */
void ExperimentUi::analysisGetWlkData(WLKData wlkData, WLKService *wlk, QString completeFilePath){
    this->wlkData = wlkData;
    this->completeFilePath = completeFilePath;
    this->wlk = wlk;
    /* 渲染 wlk 数据 */
    this->dataAnalysis();
}

/* 渲染wlk数据 */
void ExperimentUi::renderWlkData(){
    /* 临时实验属性 */
    Experiment tExp;
    tExp.experiment_name = this->wlkData.experimentName;
    tExp.user_name = this->wlkData.username;
    tExp.coding = this->wlkData.encode;
    tExp.type = this->wlkData.type;
    tExp.experiment_id = this->id;
    tExp.device_name = this->wlkData.divice_name;
    tExp.experiment_remarks = this->wlkData.experimentRemarks;
    tExp.plate_remarks = this->wlkData.plateRemarks;

    /* 临时运行页面属性 */
    QHash<QString, QString> runtimeData;
    runtimeData["reshiWendu"] = this->wlkData.reshiWendu;
    runtimeData["startTime"] = this->wlkData.startTime;
    runtimeData["endTime"] = this->wlkData.endTime;

    runtimeData["device_id"] = this->wlkData.device_id;
    runtimeData["device_series"] = this->wlkData.device_series;
    runtimeData["device_name"] = this->wlkData.divice_name;

    /* 分割wlk文件名 */
    QStringList wlkFnList = this->completeFilePath.split("/");
    if(wlkFnList.size() != 0){
        this->wlkFileName = wlkFnList[wlkFnList.size()-1];
    }

    /* 渲染实验属性 */
    experimentPropertyUi->renderWLKProperty(tExp, experimentService);

    LOG << "渲染属性完毕";

    /* 渲染扩增页面 */
    /* 回写扩增数据 */
    wlk->procedureDataPersistence(this->id, wlkData.procedureData);

    LOG << "回写扩增完毕";

    /* 发送反应板数据 */
    experimentPlateUi->getPlateData(wlkData.plateRemarks, this->wlkData.reactionPlate, wlkData.canBi);
    /* 渲染反应板属性 */
    experimentPlateUi->renderSample();

    LOG << "回写反应板完毕";

    /* 渲染运行页面数据 */
    experimentRunUi->renderRunWlkData(runtimeData);

    LOG << "回写运行页面数据完毕";

    /* 渲染结果扩增曲线 */
    experimentRunUi->saveYingguangDataList = this->wlkData.yingGuangData;
    experimentResultUi->saveYingguangDataList = this->wlkData.yingGuangData;
    experimentResultUi->saveYingguangDataListDuplicate = this->wlkData.yingGuangData;
    experimentResultUi->reactionPlate = this->wlkData.reactionPlate;

    LOG << "渲染结果完毕";

    /* 回填WLk设备 */
    this->backfillWlkDataDevice(this->wlkData.divice_name);

    LOG << "回填设备完毕";

    /* 如果荧光有数据 */
    if(wlkData.yingGuangData.size() != 0){
        /* 除反应板外，所有页面不可编辑 */
        experimentPropertyUi->allComponentsInvalid();
        experimentMethodUi->allComponentsInvalid();
        experimentRunUi->allComponentsInvalid();
    }

    /* 页面挂载 */
    emit ExperimentUi::mountPage();

//    this->renderActiveDevice();
}

/* 数据分析 */
void ExperimentUi::dataAnalysis(){
    /* 临时实验属性 */
    Experiment tExp;
    /* 初始化 */
    tExp.experiment_name = "";
    tExp.user_name = "";
    tExp.coding = "";
    tExp.type = "";
    tExp.experiment_id = "";
    tExp.experiment_remarks = "";
    tExp.plate_remarks = "";


    /* 赋值 */
    tExp.experiment_name = this->wlkData.experimentName;
    tExp.user_name = this->wlkData.username;
    tExp.coding = this->wlkData.encode;
    tExp.type = this->wlkData.type;
    tExp.experiment_id = this->id;
    tExp.device_name = this->wlkData.divice_name;
    tExp.experiment_remarks = this->wlkData.experimentRemarks;
    tExp.plate_remarks = this->wlkData.plateRemarks;

    /* 临时运行页面属性 */
    QHash<QString, QString> runtimeData;
    runtimeData["reshiWendu"] = this->wlkData.reshiWendu;
    runtimeData["startTime"] = this->wlkData.startTime;
    runtimeData["endTime"] = this->wlkData.endTime;

    runtimeData["device_id"] = this->wlkData.device_id;
    runtimeData["device_series"] = this->wlkData.device_series;
    runtimeData["device_name"] = this->wlkData.divice_name;

    /* 分割wlk文件名 */
    /* 分割wlk文件名 */
    QStringList wlkFnList = this->completeFilePath.split("/");
    if(wlkFnList.size() != 0){
        this->wlkFileName = wlkFnList[wlkFnList.size()-1];
    }

    /* 不可以点击tabbar */
    ui->stepBar->setEnabled(false);
    /* 不可以点击实验属性的下一步 */
    experimentPropertyUi->ui->nextBtn->setEnabled(false);
    /* 不可以点击实验属性的保存 */
    experimentPropertyUi->ui->saveBtn->setEnabled(false);

    /* 渲染实验属性 */
    experimentPropertyUi->renderWLKProperty(tExp, experimentService);

    LOG << "渲染属性完毕";

    /* 渲染扩增页面 */
    /* 回写扩增数据 */
    wlk->procedureDataPersistence(this->id, wlkData.procedureData);

    LOG << "回写扩增完毕";

    /* 发送反应板数据 */
    experimentPlateUi->getPlateData(this->wlkData.plateRemarks, this->wlkData.reactionPlate, this->wlkData.canBi);
    /* 渲染反应板属性 */
    LOG << 2;
    if(!experimentPlateUi->renderSample()) return;

    LOG << "回写反应板完毕";

    /* 渲染运行页面数据 */
    experimentRunUi->renderRunWlkData(runtimeData);

    LOG << "回写运行页面数据完毕";

    /* 渲染结果扩增曲线 */
    experimentRunUi->saveYingguangDataList = this->wlkData.yingGuangData;
    experimentResultUi->saveYingguangDataList = this->wlkData.yingGuangData;
    experimentResultUi->saveYingguangDataListDuplicate = this->wlkData.yingGuangData;
    experimentResultUi->reactionPlate = this->wlkData.reactionPlate;

    LOG << "渲染结果完毕";

    /* 回填WLk设备 */
    this->backfillWlkDataDevice(this->wlkData.divice_name);

    LOG << "回填设备完毕";

    /* 前三个页面组件失效 */
    experimentPropertyUi->allComponentsInvalid();
    experimentMethodUi->allComponentsInvalid();
    experimentRunUi->allComponentsInvalid();

//    this->renderActiveDevice();

    /* 可以点击tabbar */
    ui->stepBar->setEnabled(true);
    /* 可以点击实验属性的下一步 */
    experimentPropertyUi->ui->nextBtn->setEnabled(true);
    /* 不可以点击实验属性的保存 */
    experimentPropertyUi->ui->saveBtn->setEnabled(true);

    LOG << "数据分析渲染结束";

    /* 短暂延时 */
    this->sleep(SHORT_SLEEP);

    /* 跳转结果页 */
    this->dataAnalysisJump2Result();
}

/* 数据分析：跳转结果页 */
void ExperimentUi::dataAnalysisJump2Result(){
    LOG << "开始跳转结果页";
    ui->stepBar->setCurrentIndex(4);
    LOG << "跳转结果页结束";
    return;
}

/* 保存 wlk 数据 */
void ExperimentUi::saveWlkData(){
    /* 如果要是为导入wlk的结构，则与之前的wlk文件进行比较 */
    if(isImport){
        LOG << this->contrastData();
        if(!this->contrastData()){
            if(QMessageBox::Yes == cusMsg->show(this, CQuestion, "保存", "数据已被修改，是否另存实验数据？")){
                this->completeFilePath = QFileDialog::getSaveFileName(
                            this,
                            "保存文件",
                            fPath,
                            tr("Wlk Files (*.wlk)"));
                if(this->completeFilePath == "")
                    return;
            }
            else {
                return;
            }
        }
    }

    /* 获取所有实验信息 */
    /* 获取实验属性信息 */
    Experiment expData = experimentPropertyUi->sendExperimentProperty();
    /* 获取扩增程序信息 */
    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> procedureList = procedureService->getProcedureData(id);
    /* 获取反应板信息 */
    ReactionPlate reactionPlateData;
    QString canBi;
    QString reactionPlateRemarks;

    std::tuple<QString, ReactionPlate, QString> rPData = experimentPlateUi->returnPageInfos();
    std::tie(reactionPlateRemarks, reactionPlateData, canBi) = rPData;

    /* 获取运行信息 */
    QHash<QString, QString> runtimeData = experimentRunUi->sendRuntimeData();
    /* 获取荧光曲线信息 */
    QList<QList<QHash<QString, QString>>> yingguangDataList = experimentRunUi->saveYingguangDataList;
    /* 获取当前实验设备 */
    ConnectedDeviceStruct tDev;

    /* 如果是导入的设备 */
    if(isImport){
        // 从之前的wlk文件中读入设备名称，并写入新的wlkData结构体中保存
        tDev.dev.name = this->wlkData.divice_name;
        tDev.dev.id = this->wlkData.device_id;
        tDev.dev.serial_number = this->wlkData.device_series;
    }
    /* 不是导入的设备 */
    else {
        tDev = experimentRunUi->ui->runningDevice->currentData().value<ConnectedDeviceStruct>();
    }

    /* 存入所有信息 */
    WLKData wlkData;
    wlkData.experimentId = this->id;
    wlkData.reshiWendu = runtimeData["reshiWendu"];
    wlkData.startTime = runtimeData["startTime"];
    wlkData.endTime = runtimeData["endTime"];
    wlkData.divice_name = tDev.dev.name;
    wlkData.device_id = tDev.dev.id;
    wlkData.device_series = tDev.dev.serial_number;
    wlkData.experimentName = expData.experiment_name;
    wlkData.username = expData.user_name;
    wlkData.encode = expData.coding;
    wlkData.type = expData.type;
    wlkData.reactionPlate = reactionPlateData;
    wlkData.procedureData = procedureList;
    wlkData.yingGuangData = yingguangDataList;
    wlkData.canBi = canBi;
    wlkData.experimentRemarks = expData.experiment_remarks;
    wlkData.plateRemarks = reactionPlateRemarks;
    LOG << "实验信息备注LOG" << expData.experiment_remarks;
    LOG << "反应版备注LOG" << reactionPlateRemarks;

    /* 导入偏好设置的文件路径 */
    fPath = (preferencesService->getPreferencesData())["file-path"];

    LOG << completeFilePath;

    /* 打开资源管理器 */
    if(completeFilePath == ""){
        this->completeFilePath = QFileDialog::getSaveFileName(
                    this,
                    "保存文件",
                    fPath,
                    tr("Wlk Files (*.wlk)"));
    }

    if(this->completeFilePath != ""){
        /* 分割wlk文件名 */
        QStringList wlkFnList = this->completeFilePath.split("/");
        if(wlkFnList.size() != 0){
            this->wlkFileName = wlkFnList[wlkFnList.size()-1];
        }

        wlk->saveWLK(this->completeFilePath, wlkData); // 保存wlk

        cusMsg->show(this, CInformation, "保存", "文件保存成功！");
    }
}

/* 运行时保存 */
void ExperimentUi::runningSave(){
    /* 获取所有实验信息 */
    /* 获取实验属性信息 */
    Experiment expData = experimentPropertyUi->sendExperimentProperty();
    /* 获取扩增程序信息 */
    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> procedureList = procedureService->getProcedureData(id);
    /* 获取反应板信息 */
    ReactionPlate reactionPlateData;
    QString canBi;
    QString reactionPlateRemarks;

    std::tuple<QString, ReactionPlate, QString> rPData = experimentPlateUi->returnPageInfos();
    std::tie(reactionPlateRemarks, reactionPlateData, canBi) = rPData;

    /* 获取运行信息 */
    QHash<QString, QString> runtimeData = experimentRunUi->sendRuntimeData();
    /* 获取荧光曲线信息 */
    QList<QList<QHash<QString, QString>>> yingguangDataList = experimentRunUi->saveYingguangDataList;
    /* 获取当前实验设备 */
    ConnectedDeviceStruct tDev = experimentRunUi->ui->runningDevice->currentData().value<ConnectedDeviceStruct>();

    /* 存入所有信息 */
    WLKData wlkData;
    wlkData.reshiWendu = runtimeData["reshiWendu"];
    wlkData.startTime = runtimeData["startTime"];
    wlkData.endTime = runtimeData["endTime"];
    wlkData.divice_name = tDev.dev.name;
    wlkData.device_id = tDev.dev.id;
    wlkData.device_series = tDev.dev.serial_number;
    wlkData.experimentName = expData.experiment_name;
    wlkData.username = expData.user_name;
    wlkData.encode = expData.coding;
    wlkData.type = expData.type;
    wlkData.reactionPlate = reactionPlateData;
    wlkData.procedureData = procedureList;
    wlkData.yingGuangData = yingguangDataList;
    wlkData.experimentId = this->id;
    wlkData.experimentRemarks = expData.experiment_remarks;
    wlkData.experimentRemarks = reactionPlateRemarks;
    LOG << "实验保存备注" << expData.experiment_remarks;
    LOG << "反应版保存备注" << reactionPlateRemarks;

    //    LOG << "current save exp id" << this->id;

    /* 导入偏好设置的文件路径 */
    fPath = (preferencesService->getPreferencesData())["file-path"];

    LOG << completeFilePath;
    /* 打开资源管理器 */
    if(completeFilePath == ""){
        this->completeFilePath = QFileDialog::getSaveFileName(
                    this,
                    "保存文件",
                    fPath,
                    tr("Wlk Files (*.wlk)"));
    }

    if(this->completeFilePath != ""){
        wlk->saveWLK(this->completeFilePath, wlkData);
        /* 数据存储 */
        QString dirPath = QCoreApplication::applicationDirPath();
        QString dir = dirPath + "/$expRes/." + wlkData.experimentName + "_" + wlkData.divice_name + ".wlk";
        wlk->saveWLK(dir, wlkData);

    }
}

/* 运行时：强制保存wlk文件 */
void ExperimentUi::forceSaveWlkData(){
    this->runningSave();
    LOG << "this->completeFilePath" << this->completeFilePath;
    if(this->completeFilePath == ""){
        experimentRunUi->runFlag = false;
        cusMsg->show(this, CWarning, "保存", "未保存文件，实验启动失败！");

    }
    else {
        experimentRunUi->runFlag = true;
    }
}

/* 导入：对比wlk数据 */
bool ExperimentUi::contrastData(){
    LOG << "实验属性";
    /* 实验属性 */
    if(wlkData.experimentName != experimentPropertyUi->ui->expName->displayText()){
        return false;
    }
    if(wlkData.username != experimentPropertyUi->ui->userName->displayText()){
        return false;
    }
    if(wlkData.encode != experimentPropertyUi->ui->coding->displayText()){
        return false;
    }
    if(wlkData.type != experimentPropertyUi->ui->expType->currentText()){
        return false;
    }
    LOG << "实验属性完毕";
    LOG << "扩增程序";
    /* 扩增页面 */
    /* 获取当前页面扩增数据 */
    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> currentProcedureList = procedureService->getProcedureData(id);
    /* 遍历key */
    /* 阶段数不同 */
    if(wlkData.procedureData.keys().size() != currentProcedureList.keys().size()){
        return false;
    }
    LOG << "扩增程序阶段数相同";
    /* 阶段内容不同 */
    for(int i = 0; i < wlkData.procedureData.keys().size(); i++){
        if((wlkData.procedureData.keys())[i]["cycling"] != (currentProcedureList.keys())[i]["cycling"]){
            return false;
        }
    }
    LOG << "扩增程序阶段内容相同";

    /* value */
    /* 步骤数不同 */
    for(int i = 0; i < wlkData.procedureData.keys().size(); i++){
        if(wlkData.procedureData[wlkData.procedureData.keys()[i]].size() != currentProcedureList[currentProcedureList.keys()[i]].size()){
            return false;
        }
    }
    LOG << "扩增程序步骤数相同";

    /* 步骤内容不同 */
    QList<QHash<QString, QString>> stageList = wlkData.procedureData.keys();
    QList<QHash<QString, QString>> currentStageList = currentProcedureList.keys();
    /* 根据stageOrder排序阶段 */
    for(int i = 0;i < stageList.size();i ++){
        for(int j = i + 1;j < stageList.size();j ++){
            int k = stageList[i]["stage_order"].toInt();
            int l = stageList[j]["stage_order"].toInt();
            if(k > l){
                QHash<QString,QString> t = stageList[i];
                stageList[i] = stageList[j];
                stageList[j] = t;
            }
        }
    }
    for(int i = 0;i < currentStageList.size();i ++){
        for(int j = i + 1;j < currentStageList.size();j ++){
            int k = currentStageList[i]["stage_order"].toInt();
            int l = currentStageList[j]["stage_order"].toInt();
            if(k > l){
                QHash<QString,QString> t = currentStageList[i];
                currentStageList[i] = currentStageList[j];
                currentStageList[j] = t;
            }
        }
    }

    for(int i = 0; i < stageList.size(); i++){
        for(int j = 0; j < wlkData.procedureData[stageList[i]].size(); j++){
            ProcedureStep stepInfo;
            ProcedureStep currentStepInfo;
            /* 将一个步骤的数据改为结构体判断 */
            stepInfo.QHashToStruct(wlkData.procedureData[stageList[i]][j]);
            currentStepInfo.QHashToStruct(currentProcedureList[currentStageList[i]][j]);

            /* 比较步骤信息 */
            if(stepInfo.rate != currentStepInfo.rate)
                return false;
            if(stepInfo.duration != currentStepInfo.duration)
                return false;
            if(stepInfo.step_order != currentStepInfo.step_order)
                return false;
            if(stepInfo.temperature != currentStepInfo.temperature)
                return false;
            if(stepInfo.is_fluorescence != currentStepInfo.is_fluorescence)
                return false;
        }
    }
    LOG << "扩增程序完毕";

    LOG << "反应板";

    /* 反应板页面 */
    /* 耗材类型 */
    if(wlkData.reactionPlate.consumables != reactionPlate.consumables)
        return false;
    /* 样本和靶基因 */
    for(int i = 0; i < 96; i++){
        /* 样本 */
        if(wlkData.reactionPlate.sampleList[i].name != reactionPlate.sampleList[i].name)
            return false;
        if(wlkData.reactionPlate.sampleList[i].color_value != reactionPlate.sampleList[i].color_value)
            return false;
        if(wlkData.reactionPlate.sampleList[i].remarks != reactionPlate.sampleList[i].remarks)
            return false;
        if(wlkData.reactionPlate.sampleList[i].type != reactionPlate.sampleList[i].type)
            return false;

        /* 靶基因 */
        if(wlkData.reactionPlate.targetList[i][0].name != reactionPlate.targetList[i][0].name)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].type != reactionPlate.targetList[i][0].type)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].color != reactionPlate.targetList[i][0].color)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].explain != reactionPlate.targetList[i][0].explain)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].quantity != reactionPlate.targetList[i][0].quantity)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].quencher != reactionPlate.targetList[i][0].quencher)
            return false;
        if(wlkData.reactionPlate.targetList[i][0].reporter != reactionPlate.targetList[i][0].reporter)
            return false;

        if(wlkData.reactionPlate.targetList[i][1].name != reactionPlate.targetList[i][1].name)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].type != reactionPlate.targetList[i][1].type)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].color != reactionPlate.targetList[i][1].color)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].explain != reactionPlate.targetList[i][1].explain)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].quantity != reactionPlate.targetList[i][1].quantity)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].quencher != reactionPlate.targetList[i][1].quencher)
            return false;
        if(wlkData.reactionPlate.targetList[i][1].reporter != reactionPlate.targetList[i][1].reporter)
            return false;

        if(wlkData.reactionPlate.targetList[i][2].name != reactionPlate.targetList[i][2].name)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].type != reactionPlate.targetList[i][2].type)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].color != reactionPlate.targetList[i][2].color)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].explain != reactionPlate.targetList[i][2].explain)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].quantity != reactionPlate.targetList[i][2].quantity)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].quencher != reactionPlate.targetList[i][2].quencher)
            return false;
        if(wlkData.reactionPlate.targetList[i][2].reporter != reactionPlate.targetList[i][2].reporter)
            return false;

        if(wlkData.reactionPlate.targetList[i][3].name != reactionPlate.targetList[i][3].name)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].type != reactionPlate.targetList[i][3].type)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].color != reactionPlate.targetList[i][3].color)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].explain != reactionPlate.targetList[i][3].explain)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].quantity != reactionPlate.targetList[i][3].quantity)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].quencher != reactionPlate.targetList[i][3].quencher)
            return false;
        if(wlkData.reactionPlate.targetList[i][3].reporter != reactionPlate.targetList[i][3].reporter)
            return false;
    }
    LOG << "反应板完毕";
    return true;
}

/* 实验属性数据对比 */
bool ExperimentUi::contrastPropertyData(Experiment tExp){
    /* 实验类型 */
    if(this->experiment.type != tExp.type){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 实验编码 */
    else if(this->experiment.coding != tExp.coding){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 实验备注 */
    else if(this->experiment.experiment_remarks != tExp.experiment_remarks){
        /* 不相等，执行操作，返回true */
        LOG << "实验备注不相等";
        return true;
    }
    /* 用户名称 */
    else if(this->experiment.user_name != tExp.user_name){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 实验名称 */
    else if(this->experiment.experiment_name != tExp.experiment_name){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 实验反应体积 */
    else if(this->experiment.reaction_volume != tExp.reaction_volume){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 都相等，不执行操作，返回false */
    return false;
}

/* 扩增页面数据对比 */
bool ExperimentUi::contrastMethodData(std::tuple<int, int, int, int, int> basicInfo, QHash<QHash<QString, QString>, QList<QHash<QString, QString>>> tProcedureList){
    int liquidVolume, stepCount, stageCount, totalrunningTime, cyclingNumber;
    std::tie(liquidVolume, stepCount, stageCount, totalrunningTime, cyclingNumber) = basicInfo;

    /* 比较基本信息 */
    /* 反应体积 */
    if(liquidVolume != this->volumn){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 步数 */
    else if(stepCount != this->procedureStepCount){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 阶段数 */
    else if(stageCount != this->procedureStageCount){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 运行时间 */
    else if(totalrunningTime != this->totalrunningTime){
        /* 不相等，执行操作，返回true */
        return true;
    }
    /* 循环数 */
    else if(cyclingNumber != this->cycling){
        /* 不相等，执行操作，返回true */
        return true;
    }

    LOG << "基本信息相同";

    /* 基本信息都相同，比较详细信息 */
    /* 阶段内容不同 */
    if(tProcedureList.keys().size() != 0){
        for(int i = 0; i < this->procedureList.keys().size(); i++){
            if((this->procedureList.keys())[i]["cycling"] != (tProcedureList.keys())[i]["cycling"]){
                return true;
            }
        }
    }

    LOG << "阶段相同";

    /* 步骤内容不同 */
    QList<QHash<QString, QString>> stageList = this->procedureList.keys();
    QList<QHash<QString, QString>> currentStageList = tProcedureList.keys();
    /* 根据stageOrder排序阶段 */
    /* 原有步骤 */
    for(int i = 0;i < stageList.size();i ++){
        for(int j = i + 1;j < stageList.size();j ++){
            int k = stageList[i]["stage_order"].toInt();
            int l = stageList[j]["stage_order"].toInt();
            if(k > l){
                QHash<QString,QString> t = stageList[i];
                stageList[i] = stageList[j];
                stageList[j] = t;
            }
        }
    }
    /* 传入步骤 */
    for(int i = 0;i < currentStageList.size();i ++){
        for(int j = i + 1;j < currentStageList.size();j ++){
            int k = currentStageList[i]["stage_order"].toInt();
            int l = currentStageList[j]["stage_order"].toInt();
            if(k > l){
                QHash<QString,QString> t = currentStageList[i];
                currentStageList[i] = currentStageList[j];
                currentStageList[j] = t;
            }
        }
    }

    /* 比较步骤内容 */
    for(int i = 0; i < stageList.size(); i++){
        for(int j = 0; j < this->procedureList[stageList[i]].size(); j++){
            ProcedureStep stepInfo;
            ProcedureStep currentStepInfo;
            /* 将一个步骤的数据改为结构体判断 */
            stepInfo.QHashToStruct(this->procedureList[stageList[i]][j]);
            currentStepInfo.QHashToStruct(tProcedureList[currentStageList[i]][j]);

            /* 比较步骤信息 */
            if(stepInfo.rate != currentStepInfo.rate)
                return true;
            if(stepInfo.duration != currentStepInfo.duration)
                return true;
            if(stepInfo.step_order != currentStepInfo.step_order)
                return true;
            if(stepInfo.temperature != currentStepInfo.temperature)
                return true;
            if(stepInfo.is_fluorescence != currentStepInfo.is_fluorescence)
                return true;
        }
    }

    LOG << "步骤相同";

    /* 所有信息相同，不执行操作，返回false */
    return false;
}

/* 反应板页面数据对比 */
bool ExperimentUi::contrastReactionData(ReactionPlate tReaction){

    /* 耗材类型 */
    if(tReaction.consumables != this->reactionPlate.consumables)
        return true;
    /* 样本和靶基因 */
    for(int i = 0; i < 96; i++){
        /* 样本 */
        if(tReaction.sampleList[i].name != this->reactionPlate.sampleList[i].name)
            return true;
        if(tReaction.sampleList[i].color_value != this->reactionPlate.sampleList[i].color_value)
            return true;
        if(tReaction.sampleList[i].remarks != this->reactionPlate.sampleList[i].remarks)
            return true;
        if(tReaction.sampleList[i].type != this->reactionPlate.sampleList[i].type)
            return true;

        /* 靶基因1 */
        if(tReaction.targetList[i][0].name != this->reactionPlate.targetList[i][0].name)
            return true;
        if(tReaction.targetList[i][0].type != this->reactionPlate.targetList[i][0].type)
            return true;
        if(tReaction.targetList[i][0].color != this->reactionPlate.targetList[i][0].color)
            return true;
        if(tReaction.targetList[i][0].explain != this->reactionPlate.targetList[i][0].explain)
            return true;
        if(tReaction.targetList[i][0].quantity != this->reactionPlate.targetList[i][0].quantity)
            return true;
        if(tReaction.targetList[i][0].quencher != this->reactionPlate.targetList[i][0].quencher)
            return true;
        if(tReaction.targetList[i][0].reporter != this->reactionPlate.targetList[i][0].reporter)
            return true;

        /* 靶基因2 */
        if(tReaction.targetList[i][1].name != this->reactionPlate.targetList[i][1].name)
            return true;
        if(tReaction.targetList[i][1].type != this->reactionPlate.targetList[i][1].type)
            return true;
        if(tReaction.targetList[i][1].color != this->reactionPlate.targetList[i][1].color)
            return true;
        if(tReaction.targetList[i][1].explain != this->reactionPlate.targetList[i][1].explain)
            return true;
        if(tReaction.targetList[i][1].quantity != this->reactionPlate.targetList[i][1].quantity)
            return true;
        if(tReaction.targetList[i][1].quencher != this->reactionPlate.targetList[i][1].quencher)
            return true;
        if(tReaction.targetList[i][1].reporter != this->reactionPlate.targetList[i][1].reporter)
            return true;

        /* 靶基因3 */
        if(tReaction.targetList[i][2].name != this->reactionPlate.targetList[i][2].name)
            return true;
        if(tReaction.targetList[i][2].type != this->reactionPlate.targetList[i][2].type)
            return true;
        if(tReaction.targetList[i][2].color != this->reactionPlate.targetList[i][2].color)
            return true;
        if(tReaction.targetList[i][2].explain != this->reactionPlate.targetList[i][2].explain)
            return true;
        if(tReaction.targetList[i][2].quantity != this->reactionPlate.targetList[i][2].quantity)
            return true;
        if(tReaction.targetList[i][2].quencher != this->reactionPlate.targetList[i][2].quencher)
            return true;
        if(tReaction.targetList[i][2].reporter != this->reactionPlate.targetList[i][2].reporter)
            return true;

        /* 靶基因4 */
        if(tReaction.targetList[i][3].name != this->reactionPlate.targetList[i][3].name)
            return true;
        if(tReaction.targetList[i][3].type != this->reactionPlate.targetList[i][3].type)
            return true;
        if(tReaction.targetList[i][3].color != this->reactionPlate.targetList[i][3].color)
            return true;
        if(tReaction.targetList[i][3].explain != this->reactionPlate.targetList[i][3].explain)
            return true;
        if(tReaction.targetList[i][3].quantity != this->reactionPlate.targetList[i][3].quantity)
            return true;
        if(tReaction.targetList[i][3].quencher != this->reactionPlate.targetList[i][3].quencher)
            return true;
        if(tReaction.targetList[i][3].reporter != this->reactionPlate.targetList[i][3].reporter)
            return true;
    }


    LOG << "333333333333333333333333333333333>>>>>>>>>>>>>>>>>>>>>>";

    /* 所有数据均相同，不执行操作 */
    return false;
}

/* 另存为 */
void ExperimentUi::saveAsWlkData(){
    LOG << "saveAsWlkData";
    /* 获取所有实验信息 */
    /* 获取实验属性信息 */
    Experiment expData = experimentPropertyUi->sendExperimentProperty();
    /* 获取扩增程序信息 */
    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> procedureList = procedureService->getProcedureData(id);
    /* 获取反应板信息 */
    ReactionPlate reactionPlateData = experimentPlateUi->sendReactionPlate();
    /* 获取荧光曲线信息 */
    QList<QList<QHash<QString, QString>>> yingguangDataList = experimentResultUi->sendYingguangData();

    /* 存入所有信息 */
    WLKData wlkData;
    wlkData.experimentName = expData.experiment_name;
    wlkData.username = expData.user_name;
    wlkData.encode = expData.coding;
    wlkData.type = expData.type;
    wlkData.procedureData = procedureList;
    wlkData.reactionPlate = reactionPlateData;
    wlkData.yingGuangData = yingguangDataList;
    wlkData.experimentRemarks = expData.experiment_remarks;
    wlkData.plateRemarks = expData.plate_remarks;
    LOG << " 备注 " << expData.experiment_remarks << expData.plate_remarks;

    /* 另存为 */
    emit ExperimentUi::uiSaveAsWlk(wlkData);
}

/* 返回当前wlk文件名 */
QString ExperimentUi::returnCurTabWlkName(){
    if(this->completeFilePath != ""){
        /* 分割wlk文件名 */
        QStringList wlkFnList = this->completeFilePath.split("/");
        if(wlkFnList.size() != 0){
            return wlkFnList[wlkFnList.size()-1];
        }
    }
    return "";
}

/* 下一步：实验属性 - 扩增 */
void ExperimentUi::propertyToMethod(Experiment experiment){
    /* 数据同步 */
    this->experiment.experiment_name = experiment.experiment_name;
    this->experiment.user_name = experiment.user_name;
    this->experiment.coding = experiment.coding;
    this->experiment.type = experiment.type;
    this->experiment.remarks = experiment.remarks;
    this->experiment.experiment_remarks = experiment.experiment_remarks;
    this->experiment.plate_remarks = experiment.plate_remarks;
    this->experiment.reaction_volume = experiment.reaction_volume;
    this->experiment.experiment_id = this->id;

    LOG << "this->id" << this->id;

    /* 判断是否为第一次执行(flag[0] ?= 0) */
    /* 是 */
    if(this->nextFlag[0] == 0){
        this->experimentService->update(this->experiment);
        /* 计数器加1 */
        this->nextFlag[0]++;

        if(!isImport){
            /* 生成扩增数据 */
            this->procedureService->getProcedureByType(id, this->experiment.type);
        }

        /* 如果更改实验类型的提示框 */
        connect(experimentPropertyUi, &ExperimentPropertyUi::experimentTypeChanged, this, [=](Experiment experiment){
            cusMsg->show(this, CWarning, "实验类型改变，扩增程序已重置", "实验类型改变，运行条件已重置");
            /* 删除已有的扩增数据 */
            this->procedureService->deleteProcedureData(id);
            /* 生成扩增数据 */
            this->procedureService->getProcedureByType(id, experiment.type);
        });
    }
    /* 否 */
    else {
        // 更新实验信息
        this->experimentService->update(this->experiment);
    }

    LOG << "this->id, this->experiment.type" << this->id << this->experiment.type;

    /* 发送扩增阶段所需数据 */
    experimentMethodUi->getMethodData(this->id, this->experiment.type);
    /* 渲染扩增数据 */
    this->experimentMethodUi->renderProcedure(this->id);
}

/* 下一步：扩增 - 反应板 */
void ExperimentUi::methodToPlate(int volumn, int procedureStepCount, int procedureStageCount, int totalrunningTime){
    /* 写入反应体积 */
    this->volumn = volumn;
    /* 写入总步骤数 */
    this->procedureStepCount = procedureStepCount;
    /* 写入总阶段数 */
    this->procedureStageCount = procedureStageCount;
    /* 写入总运行时间 */
    this->totalrunningTime = totalrunningTime;

    /* 写入扩增数据 */
    this->procedureList = this->procedureService->getProcedureData(this->experiment.experiment_id);
}

/* 下一步：反应板 - 运行 */
void ExperimentUi::plateToRun(){
    /* 写入反应板数据 */
    /* 发送运行页面所需数据 */
    LOG << "反应版到运行函数传过来的循环数" << this->cycling;

    /* 写入运行实验页数据 */
    /* 写入反应板信息 */
    experimentRunUi->reactionPlate = this->reactionPlate;
    /* 写入实验id */
    experimentRunUi->id = this->id;
    /* 写入实验循环数 */
    experimentRunUi->totalCycling = this->cycling;
    /* 写入实验属性数据 */
    experimentRunUi->experiment = this->experiment;
    /* 写入反应体积 */
    experimentRunUi->volumn = this->volumn;
    /* 写入总步骤数 */
    experimentRunUi->procedureStepCount = this->procedureStepCount;
    /* 写入总阶段数 */
    experimentRunUi->procedureStageCount = this->procedureStageCount;
    /* 写入总运行时间 */
    experimentRunUi->totalrunningTime = this->totalrunningTime;
    /* 写入实验Service */
    experimentRunUi->experimentService = this->experimentService;

    qDebug() << "反应板 - 运行函数执行开始";
    experimentRunUi->getRunTimeData();
    LOG << "反应板 - 运行函数执行结束";
}

/* 下一步：运行 - 结果 */
void ExperimentUi::runToResult(){

    LOG << "run2result 开始更新结果页面数据";

    /* 写入结果页面所需数据 */
    /* 写入反应板数据 */
    experimentResultUi->reactionPlate = this->reactionPlate;
    /* 写入循环数 */
    experimentResultUi->cyclingNum = this->cycling;
    /* 写入实验数据 */
    experimentResultUi->experiment = this->experiment;
    /* 写入数据分析对象 */
    experimentResultUi->alyscfg = this->alysCfg;
    /* 写入偏好设置对象 */
    experimentResultUi->preferencesService = this->preferencesService;
    /* 更新曲线数据获取标识位 */
    experimentResultUi->updateCurveData = true; // 更新曲线信息

    LOG << "run2result 发送结果页面所需数据";

    /* 发送结果页面所需数据 */
    experimentResultUi->getResultData();

    LOG << "run2result 发送结果页面所需数据结束";
    LOG << "run2result 渲染结果曲线";

    /* 渲染结果曲线 */
    experimentResultUi->renderResultCurve();

    LOG << "run2result 渲染结果曲线结束";
}

/* 下一步：结果 - 导出 */
void ExperimentUi::resultToExport(){

    LOG << "返回导出信息开始";

    /* 发送 导出 所需数据 */
    experimentExportUi->experiment = this->experiment;
    experimentExportUi->reactionPlate = this->reactionPlate;
    experimentExportUi->device = experimentRunUi->cDevS;
    experimentExportUi->saveYingguangDataList = experimentResultUi->saveYingguangDataList;
    experimentExportUi->alysYingguangDataList = experimentResultUi->analysingYingGuang;
    experimentExportUi->deltaYingguangDataList = experimentResultUi->deltaYingGuang;
    experimentExportUi->exportFileService = this->exportFileService;
    experimentExportUi->procedureList = this->procedureList;
    experimentExportUi->targetLegend = this->targetLegend;
    experimentExportUi->ct = this->ct;
    experimentExportUi->preferencesService = this->preferencesService;
    experimentExportUi->experimentName = this->experiment.experiment_name;
    experimentExportUi->canBi = this->canBi;
    experimentExportUi->endTime = (experimentRunUi->sendRuntimeData())["endTime"];
    experimentExportUi->wlkFileName = this->wlkFileName;

    ui->stepBar->setEnabled(true);

    experimentExportUi->getExportData();
    experimentExportUi->setFocusToFileNameLineEdit();
    LOG << "返回导出信息结束";

}

/* 当前设备是否在运行 */
bool ExperimentUi::currentIsRunning(){
    ConnectedDeviceStruct tCdev = experimentRunUi->cDevS;
    if(tCdev.dev.name != ""){
        tCdev = currentSelectedDevice.value<ConnectedDeviceStruct>();
        for(int i = 0; i < connectDeviceInfo.size(); i++){
            if(tCdev.dev.id == connectDeviceInfo[i].dev.id){
                if(connectDeviceInfo[i].dev.status == "运行中") return true;
            }
        }
    }
    return false;
}

/* 设备关闭 */
void ExperimentUi::closeActiveDevice(){
    ConnectedDeviceStruct tCdev = experimentRunUi->cDevS;
    if(tCdev.dev.name != ""){
        for(int i = 0; i < connectDeviceInfo.size(); i++){
            if(tCdev.dev.id == connectDeviceInfo[i].dev.id){
                if(connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
                    /* 改变设备状态 */
                    connectDeviceInfo[i].dev.status = "已连接";
                    /* 关闭设备 */
                    LOG << "关闭设备前··························";
                    connectDeviceInfo[i].instructionsService->m_socketClient->closeSocket();
                    LOG << "关闭设备后··························";
                    experimentRunUi->cDevS = connectDeviceInfo[i];
                }
                break;
            }
        }
    }
}


/* 同步导出和配置文件 */
void ExperimentUi::syncExportInfo(){
    LOG << "函数执行";
    experimentExportUi->renderConfigExport();
}

/* 导出槽函数 */
void ExperimentUi::slotExport(){
    /* 获取扩增数据 */
    this->ct = experimentResultUi->returnPageInfos();
    procedureList = procedureService->getProcedureData(this->id);
//        experimentExportUi->getExportData(experiment,
//                                          reactionPlate,
//                                          experimentRunUi->cDevS,
//                                          experimentResultUi->analysingYingGuang,
//                                          exportFileService, procedureList,
//                                          this->targetLegend,
//                                          this->ct,
//                                          this->preferencesService);
    /* 发送 导出 所需数据 */
    experimentExportUi->experiment = this->experiment;
    experimentExportUi->reactionPlate = this->reactionPlate;
    experimentExportUi->device = experimentRunUi->cDevS;
    experimentExportUi->saveYingguangDataList = experimentResultUi->saveYingguangDataList;
    experimentExportUi->alysYingguangDataList = experimentResultUi->analysingYingGuang;
    experimentExportUi->deltaYingguangDataList = experimentResultUi->deltaYingGuang;
    experimentExportUi->exportFileService = this->exportFileService;
    experimentExportUi->procedureList = this->procedureList;
    experimentExportUi->targetLegend = this->targetLegend;
    experimentExportUi->ct = this->ct;
    experimentExportUi->preferencesService = this->preferencesService;
    experimentExportUi->experimentName = this->experiment.experiment_name;
    experimentExportUi->canBi = this->canBi;
    experimentExportUi->endTime = (experimentRunUi->sendRuntimeData())["endTime"];
    experimentExportUi->wlkFileName = this->wlkFileName;

    experimentExportUi->getExportData();
    /* 自动导出 */
    experimentExportUi->exportExperimentData();
}

/* 回填打开WLK文件时的设备 */
void ExperimentUi::backfillWlkDataDevice(QString wlkDeviceName){
    /* 判断当前设备列表中是否存在 */
    /* 默认不存在 */
    bool existence = false;
    QString tDevName;
    for(int i = 0; i < experimentPropertyUi->ui->sComputer->count(); i++){
        tDevName = (experimentPropertyUi->ui->sComputer->itemText(i).split(" "))[0];
        /* 设备可用 */
        if(wlkDeviceName == tDevName){
            /* 设备列表置可用设备 */
            experimentPropertyUi->ui->sComputer->setCurrentIndex(i);
            experimentRunUi->ui->runningDevice->setCurrentIndex(i);
            /* 设置运行预备设备 */
            ConnectedDeviceStruct readyDev = experimentPropertyUi->ui->sComputer->itemData(i).value<ConnectedDeviceStruct>();
            experimentRunUi->cDevS = readyDev;
            /* 设备可用状态置为true */
            existence = true;
            break;
        }
    }
    /* 如果设备不可用 */
    if(!existence){
        /* 获取当前设备列表输入框 */
        QLineEdit *comboboxEdit = experimentPropertyUi->ui->sComputer->lineEdit();
        QLineEdit *runComboboxEdit = experimentRunUi->ui->runningDevice->lineEdit();
        /* 将设备列表置为-1 */
        experimentPropertyUi->ui->sComputer->setCurrentIndex(-1);
        experimentRunUi->ui->runningDevice->setCurrentIndex(-1);
        comboboxEdit->setText(wlkDeviceName);
        runComboboxEdit->setText(wlkDeviceName);
        /* 将运行页设备状态改为未知 */
        experimentRunUi->ui->expRunStateLabel->setText("未知");
        experimentRunUi->ui->expRunStateLabel->setStyleSheet("QLabel{color: #000};font-size:16px;font-family: \"Alibaba PuHuiTi\";}");
    }
}

/* 初始化所有页面信息 */
void ExperimentUi::mountPageInfos(){
    LOG << "页面挂载" << this->thisExpIndex;
    /* 页面跳转：假装初始化时页面都渲染了 */
    ui->stepBar->setCurrentIndex(1);
    ui->stepBar->blockSignals(true); // 阻断信号
    ui->stepBar->setCurrentIndex(0); // 再跳回来
    ui->stepBar->blockSignals(false); // 解除阻断
}

/* 挂载函数 */
void ExperimentUi::mountPageFunc(){
    emit ExperimentUi::mountPage();
}

/* 休眠函数 */
void ExperimentUi::sleep(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void ExperimentUi::slotChildClosePage() {
    LOG << "ExperimentUi关闭页面";
    emit ExperimentUi::closePage();
}

